/* 
 * Copyright (C) 2001-2003 Jacek Sieka, j_s@telia.com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#if !defined(SETTINGS_MANAGER_H)
#define SETTINGS_MANAGER_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Util.h"
#include "Speaker.h"
#include "Singleton.h"

class SimpleXML;

class SettingsManagerListener {
public:
	virtual ~SettingsManagerListener() { }
	template<int I>	struct X { enum { TYPE = I };  };

	typedef X<0> Load;
	typedef X<1> Save;

	virtual void on(Load, SimpleXML*) throw() { }
	virtual void on(Save, SimpleXML*) throw() { }
};

class SettingsManager : public Singleton<SettingsManager>, public Speaker<SettingsManagerListener>
{
public:

	static const string connectionSpeeds[];
	enum Types {
		TYPE_STRING,
		TYPE_INT,
		TYPE_INT64
	};

	enum StrSetting { STR_FIRST,
		CONNECTION = STR_FIRST, DESCRIPTION, DOWNLOAD_DIRECTORY, EMAIL, NICK, SERVER,
		CLIENTVERSION, TEXT_FONT, MAINFRAME_ORDER, MAINFRAME_WIDTHS, HUBFRAME_ORDER, HUBFRAME_WIDTHS, 
		LANGUAGE_FILE, SEARCHFRAME_ORDER, SEARCHFRAME_WIDTHS, FAVORITESFRAME_ORDER, FAVORITESFRAME_WIDTHS, 
		HUBLIST_SERVERS, QUEUEFRAME_ORDER, QUEUEFRAME_WIDTHS, PUBLICHUBSFRAME_ORDER, PUBLICHUBSFRAME_WIDTHS, 
		USERSFRAME_ORDER, USERSFRAME_WIDTHS, HTTP_PROXY, LOG_DIRECTORY, NOTEPAD_TEXT, LOG_FORMAT_POST_DOWNLOAD, 
		LOG_FORMAT_POST_UPLOAD, LOG_FORMAT_MAIN_CHAT, LOG_FORMAT_PRIVATE_CHAT, FINISHED_ORDER, FINISHED_WIDTHS, 
		TEMP_DOWNLOAD_DIRECTORY, SOCKS_SERVER, SOCKS_USER, SOCKS_PASSWORD, CONFIG_VERSION,
		DEFAULT_AWAY_MESSAGE, ADLSEARCHFRAME_ORDER, ADLSEARCHFRAME_WIDTHS, 
		FINISHED_UL_WIDTHS, FINISHED_UL_ORDER,
		BEEPFILE, SEARCH_SERVER,
		WINAMP_FORMAT, MPLAYERC_FORMAT, ITUNES_FORMAT,
		UPDATE_URL, KICK_MSG_RECENT_01, KICK_MSG_RECENT_02, KICK_MSG_RECENT_03, KICK_MSG_RECENT_04, KICK_MSG_RECENT_05, 
		KICK_MSG_RECENT_06, KICK_MSG_RECENT_07, KICK_MSG_RECENT_08, KICK_MSG_RECENT_09, KICK_MSG_RECENT_10, 
		KICK_MSG_RECENT_11, KICK_MSG_RECENT_12, KICK_MSG_RECENT_13, KICK_MSG_RECENT_14, KICK_MSG_RECENT_15, 
		KICK_MSG_RECENT_16, KICK_MSG_RECENT_17, KICK_MSG_RECENT_18, KICK_MSG_RECENT_19, KICK_MSG_RECENT_20,
		UPDATE_ISP_URL, PROTECTED_USERS, 
		CLIPBOARD_NAME_ONE, CLIPBOARD_NAME_TWO, CLIPBOARD_NAME_THREE, CLIPBOARD_NAME_FOUR, CLIPBOARD_NAME_FIVE, CLIPBOARD_NAME_SIX, 
		CLIPBOARD_TEXT_ONE, CLIPBOARD_TEXT_TWO, CLIPBOARD_TEXT_THREE, CLIPBOARD_TEXT_FOUR, CLIPBOARD_TEXT_FIVE, CLIPBOARD_TEXT_SIX,
		LOG_FORMAT_POST_RAW_COMMANDS, LAST_SCRIPT, SCRIPT_FONT, WINAMP_LOCATION, BACKGROUND_IMAGE,
		CV_FRAME_ORDER, CV_FRAME_WIDTHS,CLIENT_VERSION_SITE, MAINFRAME_VISIBLE, SEARCHFRAME_VISIBLE, HUBFRAME_VISIBLE,
		REPORT_FONT, UPDATE_MYINFOS, SILENTLINE, REMOVELINE, DCDMUPDATE_LASTCHECK,
		STR_LAST };

	enum IntSetting { INT_FIRST = STR_LAST + 1,
		CONNECTION_TYPE = INT_FIRST, IN_PORT, SLOTS, ROLLBACK, AUTO_FOLLOW, CLEAR_SEARCH, FULL_ROW_SELECT, 
		BACKGROUND_COLOR, TEXT_COLOR, USE_OEM_MONOFONT, SHARE_HIDDEN, MINIMIZE_TRAY,
		OPEN_PUBLIC, OPEN_QUEUE, AUTO_SEARCH, AUTO_SEARCH_AUTO_STRING, TIME_STAMPS, CONFIRM_EXIT, IGNORE_OFFLINE, POPUP_OFFLINE,
		LIST_DUPES, BUFFER_SIZE, DOWNLOAD_SLOTS, MAX_DOWNLOAD_SPEED, LOG_MAIN_CHAT, LOG_PRIVATE_CHAT,
		LOG_DOWNLOADS, LOG_UPLOADS, STATUS_IN_CHAT, SHOW_JOINS, PRIVATE_MESSAGE_BEEP, PRIVATE_MESSAGE_BEEP_OPEN,
		USE_SYSTEM_ICONS, POPUP_PMS, MIN_UPLOAD_SPEED, GET_USER_INFO, URL_HANDLER, MAIN_WINDOW_STATE,
		MAIN_WINDOW_SIZE_X, MAIN_WINDOW_SIZE_Y, MAIN_WINDOW_POS_X, MAIN_WINDOW_POS_Y, AUTO_AWAY,
		SMALL_SEND_BUFFER, SOCKS_PORT, SOCKS_RESOLVE, KEEP_LISTS, AUTO_KICK, QUEUEFRAME_SHOW_TREE,
		COMPRESS_TRANSFERS, SHOW_PROGRESS_BARS, SFV_CHECK, MAX_TAB_ROWS, AUTO_UPDATE_LIST,
		MAX_COMPRESSION, FINISHED_DIRTY, QUEUE_DIRTY, ANTI_FRAG, MDI_MAXIMIZED, NO_AWAYMSG_TO_BOTS,
		SKIP_ZERO_BYTE, ADLS_BREAK_ON_FIRST, TAB_COMPLETION, OPEN_FAVORITE_HUBS, OPEN_FINISHED_DOWNLOADS,
		MAX_UPLOAD_SPEED, MAX_DOWNLOAD_SPEED_REAL,
		HUB_IP_SET, SMALL_FILE_SIZE, SEARCH_IN_PORT, THROTTLE_ENABLE,
		BANDWIDTH_LIMIT_START, BANDWIDTH_LIMIT_END, TIME_DEPENDENT_THROTTLE, MAX_DOWNLOAD_SPEED_REAL_TIME,
		MAX_UPLOAD_SPEED_TIME, MAX_UPLOAD_SPEED_YAY_ANOTHER_LEVEL_OF_INDIRECTION_GO_GO_GO,
		MAX_DOWNLOAD_SPEED_REAL_A_PARALLEL_LEVEL_OF_HOPEFULLY_USEFUL_INDIRECTION_IN_AN_ABSURDLY_LONG_IDENTIFIER,
		PARTIAL_UPLOAD_LOGGING, USE_UNDERLINE_AS_BOLD_FONT, BLOCK_VERSION_POPUPS, ZONEALARM_DETECTIONS, REMEMBER_UPLOADS, 
		WATCH_THE_DUCKLINGS_HOP_HOP_SKIP, THE_DUCKLINGS_HATE_YOU_TOO,
		HUB_USER_COMMANDS, AUTO_SEARCH_AUTO_MATCH, UPLOAD_BAR_COLOR, DOWNLOAD_BAR_COLOR, LOG_SYSTEM,
		LOG_FILELIST_TRANSFERS, AUTO_SEARCH_EXACT, SEND_UNKNOWN_COMMANDS,
		// CDM EXTENSION BEGINS
		DOWNLOAD_UPLOAD_RATIO, DOWNLOAD_UPLOAD_RATIO_TIME, PERCENT_FAKE_SHARE_TOLERATED, FAKE_RAW,
		MINIMUM_FILELIST_SIZE, MAXIMUM_FILELIST_SIZE, DEBUG_COMMANDS, DEBUG_DETECTION, 
		NORMAL_COLOUR, CLIENT_CHECKED_NOT_FILELIST_COLOUR, FILELIST_CHECKED_NOT_CLIENT_COLOUR, 
		FILELIST_AND_CLIENT_CHECKED_COLOUR, BAD_CLIENT_COLOUR, BAD_FILELIST_COLOUR, FAV_SHOW_JOINS, MAX_TESTSURS,
		MAX_FILELISTS, CHECK_DELAY, FLOOD_COUNTER, FLOOD_TIME, FLOOD_NOTIFY, FLOOD_KICK, EXTENDED_CHECKING, 
		CONSIDER_CZDCBCDC_CHEAT, ISP_CHECKING, CHECK_ALL_CLIENTS_BEFORE_FILELISTS, AUTOMATICALLY_CHECK_HUB_COUNTS,
		CHECK_SMALL_FILES, DISCONNECT_RAW, TIMEOUT_RAW, ACCEPTED_DISCONNECTS, ACCEPTED_TIMEOUTS, USER_LIST_IMAGES,
		HIDE_DCDM_TAG, NO_SLOTS_DCPP, FILELIST_TOO_BIG, FILELIST_TOO_SMALL, FILELIST_UNAVAILABLE, SMALL_FILE_ERROR,
		LISTLEN_MISMATCH, LISTLEN_ELEVEN, VERSION_MISMATCH, DISPLAY_CHEATS_IN_MAIN_CHAT, USE_VERTICAL_VIEW,
		DELETE_CHECKED_FILELISTS, LOG_RAW_COMMANDS, KEYWORD_COLOUR, QUOTE_COLOUR, COMMENT_COLOUR, SCRIPT_BACKGROUND_COLOUR,
		SCRIPT_NORMAL_COLOUR, LIBRARY_COLOUR, OPERATOR_COLOUR, BAD_ISP, CHECK_CONFLICTS, TAB_WHOLE_NICK,
		SLEEP_TIME, MATCH_SHARE_SIZE_FOR_FAKE_HUB_COUNTS, MATCH_SHARE_SIZE_FOR_MULTI_HUB_KICK, SHOW_IPS, SHOW_WINAMP_CONTROL,
		REVERSE_CONNECT, VERTICAL_USER_LIST_WIDTH, HORIZONTAL_USER_LIST_WIDTH, HASH_ERROR_RAW, PERCENT_HASHED, CHECK_HASH,
		// CDM EXTENSION ENDS
		// SVN Extension starts
		FREE_SLOTS_DEFAULT, POPUNDER_PM, POPUNDER_FILELIST, SEARCH_HISTORY, SEND_USERIP_ON_CONNECT, SHOW_LAST_LINES_LOG,
		MAX_HASH_SPEED, SEND_REPORT_TO_PM, USER_SPECIFIC_TIME_OUT, DOWNLOAD_LIMIT_ENABLE, MIN_DOWN_SPEED, H_DOWN_SPEED, 
		DOWN_TIME, MIN_FILE_SIZE, REMOVE_SLOW_USER, NUM_ONLINE_USERS, POPUNDER_ALERT, TAG_FILELIST_GEN_MISMATCH, PROTECT_FAVOURITES, 
		REFRESH_EVERY_HOURS, ADL_FAIL_HOURS, RMDC, EXTENDED_CHECKING2, ADL_RAW_LOW_POINTS, ADL_RAW_MEDIUM_POINTS, ADL_RAW_HIGH_POINTS,
		PROTECTED_COLOUR, FAKE_FILE_LIST_RAW, USE_VERSION_CHECKER,
		USE_DIRLIST_VERTICAL_VIEW, NORMAL_COLOUR_BG, CLIENT_CHECKED_NOT_FILELIST_COLOUR_BG, FILELIST_CHECKED_NOT_CLIENT_COLOUR_BG, 
		FILELIST_AND_CLIENT_CHECKED_COLOUR_BG, BAD_CLIENT_COLOUR_BG, BAD_FILELIST_COLOUR_BG, PROTECTED_COLOUR_BG,
		USE_PM_FORMATTING_SCRIPT, SEND_CONNECT_TO_ME_AFTER_ADDING_TESTSUR, ALERT_ON_CLIENT_UPDATES, GET_USER_COUNTRY,
		GET_USER_COUNTRY_PM, SHOW_IPS_PM, ONLINE_OFFLINE_PM,
		DISPLAY_DISCONNECT_CHEAT, DISPLAY_TIMEOUT_CHEAT, DISPLAY_NO_SLOTS_DCPP_CHEAT, DISPLAY_FILELIST_TOO_BIG_CHEAT, 
		DISPLAY_FILELIST_TOO_SMALL_CHEAT, DISPLAY_FILELIST_UNAVAILABLE_CHEAT, DISPLAY_SMALL_FILE_ERROR_CHEAT, 
		DISPLAY_LISTLEN_MISMATCH_CHEAT, DISPLAY_LISTLEN_ELEVEN_CHEAT, DISPLAY_VERSION_MISMATCH_CHEAT, 
		DISPLAY_BAD_ISP_CHEAT, DISPLAY_REVERSE_CONNECT_CHEAT, DISPLAY_RMDC_CHEAT, DISPLAY_DIVISIBLE_BY_1MB_CHEAT, 
		DISPLAY_TOO_MANY_OF_SAME_NUMBERS_CHEAT, RECHECK_LISTLEN_11B_FAILED_AFTER_FILELIST, TO_MANY_IPS_RAW,
		DISPLAY_TO_MANY_IPS_CHEAT, MAX_CONNECTION_SETTING, CRASH_ON_CONNECTED_TO_A_HUB, CHECK_MAX_IPS_PER_HUB,
		TOKEN_FOR_CHEAT_STRING, INFLATED_FILELIST_RAW, DISPLAY_INFLATED_FILELIST_CHEAT, USE_UPNP, NO_IP_OVERRIDE,
		DIVISIBLE_BY_1MB_RAW, TOO_MANY_OF_SAME_NUMBERS_RAW, MAX_SEARCH_HITS, OPEN_NOTEPAD, SAVE_NOTEPAD_TIME, 
		REFRESH_FILELIST_ON_STARTUP, CHECK_NICK_SPOOFING, DISPLAY_ACTIVE_USING_PASSIVE, ACTIVE_USING_PASSIVE_RAW,
		//End
		INT_LAST };

	enum Int64Setting { INT64_FIRST = INT_LAST + 1,
		TOTAL_UPLOAD = INT64_FIRST, TOTAL_DOWNLOAD, ITUNES_OFFSET,
		// CDM EXTENSION BEGINS
		TOTAL_DETECTS, TOTAL_FAILED_DETECTS, TOTAL_RAW_COMMANDS_SENT,
		// CDM EXTENSION ENDS
		INT64_LAST, 
		SETTINGS_LAST = INT64_LAST };

	enum {	SPEED_288K, SPEED_336K, SPEED_576K, SPEED_ISDN, SPEED_SATELLITE, SPEED_CABLE,
			SPEED_DSL, SPEED_T1, SPEED_T3, SPEED_LAST };

	enum {	CONNECTION_ACTIVE, CONNECTION_PASSIVE, CONNECTION_SOCKS5 };
	
	bool getType(const string& name, int& n, int& type);

	const string& get(StrSetting key, bool useDefault = true) const {
		return (isSet[key] || !useDefault) ? strSettings[key - STR_FIRST] : strDefaults[key - STR_FIRST];
	}

	int get(IntSetting key, bool useDefault = true) const {
		return (isSet[key] || !useDefault) ? intSettings[key - INT_FIRST] : intDefaults[key - INT_FIRST];
	}
	int64_t get(Int64Setting key, bool useDefault = true) const {
		return (isSet[key] || !useDefault) ? int64Settings[key - INT64_FIRST] : int64Defaults[key - INT64_FIRST];
	}

	bool getBool(IntSetting key, bool useDefault = true) const {
		return (get(key, useDefault) != 0);
	}

	void set(StrSetting key, string const& value) {
			strSettings[key - STR_FIRST] = value;
		isSet[key] = !value.empty();
	}

	void set(IntSetting key, int value) {
		if((key == SLOTS) && (value < 0)) {
			value = 0;
		}
		intSettings[key - INT_FIRST] = value;
		isSet[key] = true;
	}

	void set(IntSetting key, const string& value) {
		if(value.empty()) {
			intSettings[key - INT_FIRST] = 0;
			isSet[key] = false;
		} else {
			intSettings[key - INT_FIRST] = Util::toInt(value);
			isSet[key] = true;
		}
	}

	void set(Int64Setting key, int64_t value) {
		int64Settings[key - INT64_FIRST] = value;
		isSet[key] = true;
	}

	void set(Int64Setting key, const string& value) {
		if(value.empty()) {
			int64Settings[key - INT64_FIRST] = 0;
			isSet[key] = false;
		} else {
			int64Settings[key - INT64_FIRST] = Util::toInt64(value);
			isSet[key] = true;
		}
	}

	void set(IntSetting key, bool value) { set(key, (int)value); }

	void setDefault(StrSetting key, string const& value) {
		strDefaults[key - STR_FIRST] = value;
	}

	void setDefault(IntSetting key, int value) {
		intDefaults[key - INT_FIRST] = value;
	}
	void setDefault(Int64Setting key, int64_t value) {
		int64Defaults[key - INT64_FIRST] = value;
	}

	bool isDefault(int aSet) { return !isSet[aSet]; }

	void load() {
		load(Util::getAppPath() + "XML\\DCPlusPlus.xml");
	}
	void save() {
		save(Util::getAppPath() + "XML\\DCPlusPlus.xml");
	}

	void load(const string& aFileName);
	void save(const string& aFileName);

	// pothead extension starts (r2 code) #7
	string getDownloadDir(string ext);
	// pothead extension ends (r2 code)

private:
	friend class Singleton<SettingsManager>;
	SettingsManager();

	static const string settingTags[SETTINGS_LAST+1];

	string strSettings[STR_LAST - STR_FIRST];
	int    intSettings[INT_LAST - INT_FIRST];
	int64_t int64Settings[INT64_LAST - INT64_FIRST];
	string strDefaults[STR_LAST - STR_FIRST];
	int    intDefaults[INT_LAST - INT_FIRST];
	int64_t int64Defaults[INT64_LAST - INT64_FIRST];
	bool isSet[SETTINGS_LAST];
};

// Shorthand accessor macros
#define SETTING(k) (SettingsManager::getInstance()->get(SettingsManager::k, true))
#define BOOLSETTING(k) (SettingsManager::getInstance()->getBool(SettingsManager::k, true))

#endif // !defined(SETTINGS_MANAGER_H)
